#include "stdafx.h"
#include "Agent.h"
#include "emotionalmemory.h"
#include "action_idle.h"

using namespace BAA;

Agent::Agent(const std::string name):BasicObject(name)
{
	this->world = World::getInstance();
}

void BAA::Agent::Create()
{
	mProperties = new AgentProperties("properties");
	mAppraisalProcess = new Appraisal("appraisal");
	mRoleSetMap = new StringRoleMap();
	mPlanningEngine = new PlanningEngine("planner");

	// create children that require it.
	mProperties->Create();
	mPlanningEngine->Create();

	mActionIdle = new Action_Idle();
	mCurrentAction = mActionIdle;
	mCurrentAction->Complete(true);
}


void BAA::Agent::Initialize()
{
	// initialize
	mProperties->Initialize(this);
	mAppraisalProcess->Initialize(this);
	mPlanningEngine->Initialize(this);
	//mCurrentAction->Initialize(this,new AgentPointerMap());



}

void BAA::Agent::AddRole( Role * role, AgentPointerMap * roleTargets, float importance)
{

	// for role value - add values to appraisal process
	if(role == NULL)
		return;

	role->Initialize(this, roleTargets, importance);

	// setup appraisal process for values

	// get each value from the ValueValueMap
	for(ValueValueMap::iterator iter = role->Values()->begin(); iter != role->Values()->end();++iter)
	{
		mAppraisalProcess->AddValue(iter->second);
	}

	// get each value from the ValueValueMap
	for(StringGoalMap::iterator iter = role->Goals()->begin(); iter != role->Goals()->end();++iter)
	{
		mAppraisalProcess->AddGoal(iter->second);
	}


	// for role goal  - add goal   to appraisal process

	// for role action - add action to action map 

	for(StringActionMap::iterator it = role->Actions()->begin(); it != role->Actions()->end(); ++it)
	{
		for(std::vector<std::string>::iterator iter = it->second->Postcondition()->begin();
			iter != it->second->Postcondition()->end(); ++iter)
		{
			mPlanningEngine->AddAction((*iter), it->second);
		}		
	}




	// add role to rolesetmap
	if(mRoleSetMap)
		(*mRoleSetMap)[role->Name()] = role;


}

void BAA::Agent::Clear()
{
	mAppraisalProcess->Clear();
}





/// performs an update on this agent
void BAA::Agent::Update( GameTime time )
{
	//////////////////////////////////////////////////////////////////////////
	// 1.
	// checks to see there is an event for this agent.
	// if an event exists, appraise it
	// if event causes emotional memories, 
	//		integrate memories into agent.
	//
	// 2.
	// emotions, personalities, Active Emotional Memory
	//
	// 3.
	// Select Goal with highest utility given emotional and personality state
	//        Add the emotional 
	// 
	//4. 
	// If no plan exists for the current goal
	// Create a new partial plan
	// If a plan exists, check to see a better plan comes to mind.
	// 
	//5. 
	// Perform Action
	//////////////////////////////////////////////////////////////////////////

	//1. Events.

	// assume event is complete right away
	if(mCurrentAction != NULL)
		mCurrentAction->Complete(true);

	std::vector<Event*>* events;
	if(world != NULL)
		events=  world->getEventsForAgent(this->Name());

	// we have events to appraise
	if(events != NULL && events->size() != 0)
	{

		for(std::vector<Event*>::iterator it = events->begin(); it != events->end(); ++it)
		{
			Event* event = (*it);
			//if(event->time.current > time.current)
			//{
			// pass event to appraisal stage
			this->mAppraisalProcess->AppraiseEvent(event);
			//}
		}
		// appraisals complete

		// integrate emotional memories into roles.

		// mAppraisedEvent  //
	}

	// 2. Updates.

	// update AgentProperties ( emotion,personality)
	mProperties->Update(time);

	// TODO : Update Role Emotions



	// update Active Emotional Memory; currently performing simple averaging of 
	// active emotional memories.
	//UpdateActiveEmotionalMemory(time);


	//3. Select Best Goal

	Goal * bestGoal = SelectBestGoal();

	//4. Construct Plan Tree

	PlanTreeNode* planTree = mPlanningEngine->Update(this,bestGoal);

	std::vector<Action*>* plan = mPlanningEngine->Plan();

	// push action to the world.

	if(mCurrentAction != NULL && mCurrentAction->Complete())
	{
		// remove last action
		if(plan)
		{

			if(!plan->empty())
			{

				mCurrentAction = plan->back();
				mCurrentAction->Complete(false);
				plan->pop_back();

				// set action to be peformed.
				// tell world we are performing action

				world->CreateAgentEvent(this,mCurrentAction);
			}
		}

	}
	else
	{
		// current action = IDLE
	}








}

void BAA::Agent::UpdateActiveEmotionalMemory( GameTime time )
{

	// aggregate the new 

	//float anger=0;
	//float fear=0;
	//float sadness=0;
	//float disgust=0;
	//float surprise=0;
	//float happyness=0;

	//for(vector<EmotionalMemory*>::iterator it = mActiveEmotionalMemory.begin();
	//	it != mActiveEmotionalMemory.end(); ++it)
	//{
	//	StringEmotionMap * emotions = (*it)->EmotionMap();

	//	Emotion * emotion = (*emotions)["anger"];
	//	if(emotion!= NULL)
	//		anger += (*emotion).GetValue();

	//	emotion = (*emotions)["fear"];
	//	if(emotion!= NULL)
	//		fear += (*emotion).GetValue();

	//	emotion = (*emotions)["sadness"];
	//	if(emotion!= NULL)
	//		sadness += (*emotion).GetValue();

	//	emotion = (*emotions)["disgust"];
	//	if(emotion!= NULL)
	//		disgust += (*emotion).GetValue();

	//	emotion = (*emotions)["surprise"];
	//	if(emotion!= NULL)
	//		surprise += (*emotion).GetValue();

	//	emotion = (*emotions)["happyness"];
	//	if(emotion!= NULL)
	//		happyness += (*emotion).GetValue();
	//}

	//float memSize = mActiveEmotionalMemory.size();

	//if(memSize == 0)
	//	memSize = 1;

	//// get and set average state.
	//if(mProperties->mAnger != NULL)
	//	mProperties->mAnger->SetValue(anger/memSize);

	//if(mProperties->mAnger != NULL)
	//	mProperties->mFear->SetValue(fear/memSize);

	//if(mProperties->mSadness != NULL)
	//	mProperties->mSadness->SetValue(sadness/memSize);

	//if(mProperties->mDisgust != NULL)
	//	mProperties->mDisgust->SetValue(disgust/memSize);

	//if(mProperties->mSurprise != NULL)
	//	mProperties->mSurprise->SetValue(surprise/memSize);

	//if(mProperties->mHappyness != NULL)
	//	mProperties->mHappyness->SetValue(happyness/memSize);


	// old memories should be removed. 
	// SKIP for now.
}

Goal* BAA::Agent::SelectBestGoal()
{

	Goal * bestGoal = NULL;
	float highestUtility = -99999999.0f;
	float goalUtility = 0;
	float roleImportance=0;

	// for each role
	for(StringRoleMap::iterator it = mRoleSetMap->begin(); it != mRoleSetMap->end();++it)
	{
		// get importance of the role
		roleImportance = (*it).second->RoleImportance();

		//for each goal.
		StringGoalMap * goals = (*it).second->Goals();
		for(StringGoalMap::iterator iter = goals->begin(); iter != goals->end(); ++iter)
		{
			// calculate its utility
			goalUtility = roleImportance * (iter->second->CalculateStateUtility(this));

			// CONSEQUENCE OF SELECTING THIS GOAL SHOULD ALSO BE EVALUTATE HERE!

			// get list of actions solve the goal, get highest value,
			// TODO

			// if we have found a goal with higher utility
			// update the best goal and its utility
			if(goalUtility > highestUtility)
			{
				highestUtility = goalUtility;
				bestGoal = iter->second;
			}

		}// end for goals
	}//end for roles

	return bestGoal;
}

BAA::Agent::~Agent()
{
	mProperties->~AgentProperties();
	mAppraisalProcess->~Appraisal();
	mRoleSetMap->~map();
	mPlanningEngine->~PlanningEngine();
}
